這篇教學會介紹如何使用 OpenCV 裡的單物件追蹤功能 ( tracker ),並搭配 cv2.selectROI 選取需要追蹤的物體,就能即時進行該物件的追蹤。
原文參考:OpenCV 單物件追蹤
因為程式中的 OpenCV 會需要使用鏡頭或 GPU,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda ) ,並安裝 OpenCV 函式庫 ( 參考:OpenCV 函式庫 )。
OpenCV 提供了八種物件追蹤的演算法,演算法的速度和精準度如下表所示:
演算法 | 速度 | 精準度 | 說明 |
---|---|---|---|
BOOSTING | 慢 | 差 | 元老級追蹤器,速度較慢,並且不是很準確。 |
MIL | 慢 | 差 | 比 BOOSTING 更精確,但仍然不是很準確。 |
GOTURN | 中 | 中 | 需要搭配深度運算模型才能運作的追蹤器。 |
TLD | 中 | 中 | 速度普通,精準度普通的追蹤器。 |
MEDIANFLOW | 中 | 中 | 對於會跳動或快速移動的物件,判斷不是很準確。 |
KCF | 快 | 高 | 不錯的追蹤器,但在物件被遮蔽的狀態下不是很準確。 |
MOSSE | 最快 | 高 | 速度最快,但精準度比 KCF 和 CSRT 稍差。 |
CSRT | 快 | 最高 | 精準度比 KCF 好,但速度比 KCF 慢。 |
使用 Python 時創建追蹤器的語法如下:
演算法 | 創建語法 |
---|---|
BOOSTING | cv2.TrackerBoosting_create() |
MIL | cv2.TrackerMIL_create() |
GOTURN | cv2.TrackerGOTURN_create() |
TLD | cv2.TrackerTLD_create() |
MEDIANFLOW | cv2.TrackerMedianFlow_create() |
KCF | cv2.TrackerKCF_create() |
MOSSE | cv2.TrackerMOSSE_create() |
CSRT | cv2.TrackerCSRT_create() |
要進行物件追蹤,必須先選取特定區域,OpenCV 內建 cv2.selectROI 方法可以進行選取的功能,使用方法如下:
area = cv2.selectROI('視窗名稱', frame, showCrosshair=False, fromCenter=False)
# area:(x, y, width, height)
# frame:要選取的影像
# showCrosshair:選取框中間是否要有十字線,預設 True
# fromCenter:True 中心點選取,False 右上角選取
下方的程式碼執行後,按下鍵盤按鍵 a 就會進入選取模式,此時攝影機畫面會暫停,使用滑鼠拖拉選取後,按下 enter 鍵,就會回傳 xy 座標以及長寬尺寸。
import cv2
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, frame = cap.read()
if not ret:
print("Cannot receive frame")
break
keyName = cv2.waitKey(1)
# 按下 q 結束
if keyName == ord('q'):
break
# 按下 a 開始選取
if keyName == ord('a'):
# 選取區域
area = cv2.selectROI('oxxostudio', frame, showCrosshair=False, fromCenter=False)
print(area)
cv2.imshow('oxxostudio', frame)
cap.release()
cv2.destroyAllWindows()
透過 cv2.selectROI 方法取得區域位置和尺寸後,將位置和尺寸提交給透過 cv2.TrackerCSRT_create() 所創建的追蹤器,搭配 tracker.init 追蹤器初始化以及 tracker.update 追蹤器更新的方法,就能即時追蹤畫面中的特定物體。
下方的程式碼執行後,視窗中會看見攝影機的即時影像,按下鍵盤的 a 後影像會暫停,進入擷取模式,透過滑鼠拖曳出要追蹤的物件區域,按下 Enter 後就會出現紅色追蹤外框,開始追蹤特定的物件。
import cv2
tracker = cv2.TrackerCSRT_create() # 創建追蹤器
tracking = False # 設定 False 表示尚未開始追蹤
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, frame = cap.read()
if not ret:
print("Cannot receive frame")
break
frame = cv2.resize(frame,(540,300)) # 縮小尺寸,加快速度
keyName = cv2.waitKey(1)
if keyName == ord('q'):
break
if keyName == ord('a'):
area = cv2.selectROI('oxxostudio', frame, showCrosshair=False, fromCenter=False)
tracker.init(frame, area) # 初始化追蹤器
tracking = True # 設定可以開始追蹤
if tracking:
success, point = tracker.update(frame) # 追蹤成功後,不斷回傳左上和右下的座標
if success:
p1 = [int(point[0]), int(point[1])]
p2 = [int(point[0] + point[2]), int(point[1] + point[3])]
cv2.rectangle(frame, p1, p2, (0,0,255), 3) # 根據座標,繪製四邊形,框住要追蹤的物件
cv2.imshow('oxxostudio', frame)
cap.release()
cv2.destroyAllWindows()
大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我已經寫了超過 400 篇 Python 的教學,有興趣可以參考下方連結呦~ ^_^